using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using Zsa.Emulation.Input;


namespace Zsa.Emulation.Render.Input.Win32
{
    /// <summary>
    /// Win32 Keyboard input that catches all keyboard input in the application.
    /// </summary>
    public class GlobalKeyboardInput : ControllerDeviceManager, IMessageFilter
    {

        #region Fields
        /// <summary>
        /// True if message filter is attached.
        /// </summary>
        private bool _IsAttached = false;

        /// <summary>
        /// The nes key config.
        /// </summary>
        private int[] _NesInputKeys;

        /// <summary>
        /// The hot keys.
        /// </summary>
        private int[] _HotKeys;
        
        #endregion Fields

        #region Constructor
        /// <summary>
        /// Initializes a new instance of the <see cref="T:KeyboardInput"/> class.
        /// </summary>
        /// <param name="settings">The settings.</param>
        public GlobalKeyboardInput(KeyboardInputSettings settings)
            : base ( settings )
        {
            _NesInputKeys = settings.NesInputKeys;
        }
        #endregion Constructor

        #region Methods



        /// <summary>
        /// Filters out a message before it is dispatched.
        /// </summary>
        /// <param name="m">The message to be dispatched. You cannot modify this message.</param>
        /// <returns>
        /// true to filter the message and stop it from being dispatched; false to allow the message to continue to the next filter or control.
        /// </returns>
        bool IMessageFilter.PreFilterMessage(ref Message m)
        {
            if (m.Msg != 0x100 && m.Msg != 0x101)
            {
                return false;
            }
            int _Key = ((int)m.WParam);
            for (int _TempIndex = 0; _TempIndex < _NesInputKeys.Length; _TempIndex++)
            {
                if (_NesInputKeys[_TempIndex] == _Key)
                {
                    if (m.Msg == 0x100)
                    {
                        base.NesKeyPressed(0, (NesInputButton)((_TempIndex % 8) + 1));
                    }
                    else
                    {
                        base.NesKeyReleased(0, (NesInputButton)((_TempIndex % 8) + 1));
                    }
                    return true;
                }
            }


            return false;
        }

        /// <summary>
        /// Creates or recreates the device.
        /// </summary>
        protected override void OnRecreateDevice()
        {

            ReleaseHook();
            try
            {
                Application.AddMessageFilter(this);
                _IsAttached = true;
            }
            catch (Exception excep)
            {
                Console.WriteLine(excep);
            }
        }


        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// </summary>
        private void ReleaseHook()
        {
            if (_IsAttached)
            {
                try
                {
                    Application.RemoveMessageFilter(this);
                }
                catch ( Exception excep )
                {
                    Console.WriteLine(excep);
                }
            }
        }

        /// <summary>
        /// Called when [dispose].
        /// </summary>
        protected override void OnDispose()
        {
           ReleaseHook();
        }
        #endregion Methods
    }
}
